package ${projectDomain}.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import ${projectDomain}.adapter.logger.LoggerQueueAdapter;
import ${projectDomain}.annotation.logger.QueueReceive;
import ${projectDomain}.annotation.logger.QueueSend;
import ${projectDomain}.core.CommonOperator;
import ${projectDomain}.pojo.IBaseMro;
import ${projectDomain}.pojo.IBaseMso;
import ${projectDomain}.pojo.dao.logger.queue.LoggerQueueInsertDo;
import ${projectDomain}.pojo.dao.logger.queue.LoggerQueueUpdateDo;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.JsonUtils;
import com.unswift.utils.ObjectUtils;

@Aspect
@Component
@Api(value="Rabbit Mq Aop，负责处理@QueueSend和@QueueReceive注解", author = "unswift", date = "2023-10-05", version = "1.0.0")
public class RabbitAop extends CommonOperator{

	@Autowired
	private LoggerQueueAdapter loggerQueueAdapter;
	
	@ApiMethod("队列消息发送切面规则")
	@Pointcut("@annotation(${projectDomain}.annotation.logger.QueueSend)")
	public void entryQueueSendPoint() {
	}
	
	@ApiMethod(value="队列消息发送的切面实现", params = {@ApiField("切面的方法封装"), @ApiField("权限注解")})
	@Around("entryQueueSendPoint() && @annotation(send)")
	public Object around(ProceedingJoinPoint point, QueueSend send) throws Throwable {
		Object[] args=null;
		IBaseMso sendContent=null;
		try {
			args=point.getArgs();
			sendContent=(IBaseMso)args[2];
			Long businessId=saveLoggerQueue((String)args[0], (String)args[1], sendContent);
			sendContent.setBusinessId(businessId);
			Object result = point.proceed();
			return result;
		} catch (Exception e) {
			throw e;
		}
	}
	
	@ApiMethod("队列消息接收切面规则")
	@Pointcut("@annotation(${projectDomain}.annotation.logger.QueueReceive)")
	public void entryQueueReceivePoint() {
	}
	
	@ApiMethod(value="队列消息接收的切面实现", params = {@ApiField("切面的方法封装"), @ApiField("权限注解")})
	@Around("entryQueueReceivePoint() && @annotation(receive) && @annotation(listener)")
	public Object around(ProceedingJoinPoint point, QueueReceive receive, RabbitListener listener) throws Throwable {
		Object[] args=null;
		IBaseMro receiveContent=null;
		String exceptionMessage=null;
		try {
			args=point.getArgs();
			receiveContent=(IBaseMro)args[0];
			if(ObjectUtils.isNotEmpty(exceptionMessage)) {
				ExceptionUtils.setLanguage(receiveContent.getLanguage().toUpperCase());//设置异常使用的语言
			}
			Object result = point.proceed();
			return result;
		} catch (Exception e) {
			exceptionMessage=ExceptionUtils.getStackTrace(e);
			throw e;
		} finally {
			updateLoggerQueue(receiveContent.getBusinessId(), listener.queues()[0], exceptionMessage, receiveContent.getToken());
		}
	}
	
	@ApiMethod(value="存储队列发送日志", params = {@ApiField("队列交换机"), @ApiField("队列路由"), @ApiField("队列发送内容对象")})
	private Long saveLoggerQueue(String exchangeName, String routeKey, IBaseMso sendContent) {
		LoggerQueueInsertDo insert=new LoggerQueueInsertDo();
		insert.setExchangeName(exchangeName);
		insert.setRouteKey(routeKey);
		insert.setMessage(JsonUtils.toJson(sendContent));
		insert.setStatus((byte)0);
		loggerQueueAdapter.save(insert, false);
		return insert.getId();
	}
	
	@ApiMethod(value="更新队列发送日志-队列消费时执行", params = {@ApiField("业务id即日志id"),@ApiField("队列名称"),@ApiField("如果消费发生异常，则为异常消息堆栈"), @ApiField("发送消息的用户")})
	private void updateLoggerQueue(Long businessId, String queueName, String exceptionMessage, String token) {
		LoggerQueueUpdateDo update=new LoggerQueueUpdateDo();
		update.setId(businessId);
		update.setQueueName(queueName);
		update.setStatus((byte)1);
		if(ObjectUtils.isEmpty(exceptionMessage)) {
			update.setResult((byte)1);
		}else {
			update.setResult((byte)0);
			update.setErrorMessage(exceptionMessage);
		}
		update.setChangeUser(this.getUserId(token));
		loggerQueueAdapter.update(update, false);
	}
}
